#ifndef BST_H
#define BST_H

#include <functional>
#include <ostream>
#include <sstream>
class BST
{
public:
    class Node {
    public:
	    Node(int value, Node* left, Node* right) :
        value(value),
        left(left),right(right) {};

	    Node() : value(0) , left(nullptr) , right(nullptr) {};
	    Node(const Node& node) : value(node.value) ,left(node.left) ,right(node.right) {}

	    int value;
	    Node* left;
	    Node* right;

        bool operator==(int b) {
            return b == value;
        }
        bool operator>(int b) {
            return value > b;
        }

        bool operator<(int b) {
            return value < b;
        }

        bool operator>=(int b) {
            return value >= b;
        }
        bool operator<=(int b) {
            return value <= b;
        }
        friend std::ostream& operator<<( std::ostream& os , const Node& n ) {
            std::stringstream ss;
            ss  << static_cast<const void *>(&n) 
                << "\t=> value:" << n.value
                << "\tleft:" << static_cast<const void *>(n.left)
                << "\tright:"<< static_cast<const void *>(n.right);
            os << ss.str();
            return os;      
        }

        friend bool operator>(int a , const BST::Node& nb) {
            return a > nb.value;
        }
        friend bool operator>=(int a , const BST::Node& nb) {
            return a >= nb.value;
        }        
        friend bool operator<(int a , const BST::Node& nb) {
            return a < nb.value;
        }
        friend bool operator<=(int a , const BST::Node& nb) {
            return a <= nb.value;
        }
    };
    BST() {
        root = nullptr;
        num  = 0;
    };
    BST( const BST & other );
    BST( BST && other ) noexcept;
    BST( std::initializer_list<int> list );
    ~BST();

    BST& operator=( const BST & other );
    BST& operator=( BST && other );
    BST& operator++();
    BST operator++(int fxxk_cpp);

    Node*& get_root() {
        return root;
    };
    void bfs(std::function<void(Node*& node)> func);
    size_t length() {
        return num;
    };
    bool add_node(int value);
    Node** find_node(int value);
    Node** find_parrent(int value);
    Node** find_successor(int value);
    bool delete_node(int value);
    friend std::ostream& operator<<(std::ostream& os , const BST& tree );
private:
    Node* root;
    size_t num;
};

#endif //BST_H